"""
回测用的模拟管理器

提供订单管理和账户管理的模拟实现
"""

from typing import Dict, List, Optional, Any
from datetime import datetime
from decimal import Decimal
import uuid


class MockOrderManager:
    """模拟订单管理器"""
    
    def __init__(self):
        self.orders = {}
        self.order_history = []
        self.next_order_id = 1
    
    def place_order(self, symbol: str, side: str, order_type: str, 
                   quantity: float, price: Optional[float] = None, 
                   **kwargs) -> str:
        """下单"""
        order_id = f"mock_{self.next_order_id}"
        self.next_order_id += 1
        
        order = {
            'order_id': order_id,
            'symbol': symbol,
            'side': side,
            'type': order_type,
            'quantity': quantity,
            'price': price,
            'status': 'pending',
            'filled_quantity': 0,
            'filled_price': 0,
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),  # 统一格式
            'kwargs': kwargs
        }
        
        self.orders[order_id] = order
        return order_id
    
    def cancel_order(self, order_id: str) -> bool:
        """撤单"""
        if order_id in self.orders:
            self.orders[order_id]['status'] = 'cancelled'
            return True
        return False
    
    def get_order(self, order_id: str) -> Optional[Dict]:
        """获取订单信息"""
        return self.orders.get(order_id)
    
    def get_open_orders(self, symbol: Optional[str] = None) -> List[Dict]:
        """获取未完成订单"""
        orders = []
        for order in self.orders.values():
            if order['status'] in ['pending', 'partial']:
                if symbol is None or order['symbol'] == symbol:
                    orders.append(order)
        return orders
    
    def get_order_history(self, symbol: Optional[str] = None, 
                         limit: int = 100) -> List[Dict]:
        """获取历史订单"""
        history = self.order_history[-limit:] if limit else self.order_history
        if symbol:
            history = [order for order in history if order['symbol'] == symbol]
        return history
    
    def simulate_fill(self, order_id: str, fill_price: float, 
                     fill_quantity: Optional[float] = None) -> bool:
        """模拟成交"""
        if order_id not in self.orders:
            return False
        
        order = self.orders[order_id]
        if order['status'] not in ['pending', 'partial']:
            return False
        
        if fill_quantity is None:
            fill_quantity = order['quantity'] - order['filled_quantity']
        
        # 更新成交信息
        order['filled_quantity'] += fill_quantity
        order['filled_price'] = fill_price
        
        # 更新状态
        if order['filled_quantity'] >= order['quantity']:
            order['status'] = 'filled'
            # 移动到历史记录
            self.order_history.append(order.copy())
            del self.orders[order_id]
        else:
            order['status'] = 'partial'
        
        return True


class MockAccountManager:
    """模拟账户管理器"""
    
    def __init__(self, initial_balance: float = 10000):
        self.balances = {
            'USDT': initial_balance,
            'BTC': 0,
            'ETH': 0
        }
        self.frozen_balances = {
            'USDT': 0,
            'BTC': 0,
            'ETH': 0
        }
        self.positions = {}
        self.transaction_history = []
    
    def get_balance(self, asset: str) -> Dict[str, float]:
        """获取余额"""
        return {
            'free': self.balances.get(asset, 0) - self.frozen_balances.get(asset, 0),
            'locked': self.frozen_balances.get(asset, 0),
            'total': self.balances.get(asset, 0)
        }
    
    def get_all_balances(self) -> Dict[str, Dict[str, float]]:
        """获取所有余额"""
        result = {}
        for asset in self.balances:
            result[asset] = self.get_balance(asset)
        return result
    
    def freeze_balance(self, asset: str, amount: float) -> bool:
        """冻结余额"""
        available = self.balances.get(asset, 0) - self.frozen_balances.get(asset, 0)
        if available >= amount:
            self.frozen_balances[asset] = self.frozen_balances.get(asset, 0) + amount
            return True
        return False
    
    def unfreeze_balance(self, asset: str, amount: float) -> bool:
        """解冻余额"""
        frozen = self.frozen_balances.get(asset, 0)
        if frozen >= amount:
            self.frozen_balances[asset] = frozen - amount
            return True
        return False
    
    def update_balance(self, asset: str, amount: float, 
                      transaction_type: str = 'trade') -> bool:
        """更新余额"""
        current_balance = self.balances.get(asset, 0)
        new_balance = current_balance + amount
        
        if new_balance < 0:
            return False
        
        self.balances[asset] = new_balance
        
        # 记录交易历史
        self.transaction_history.append({
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),  # 统一格式
            'asset': asset,
            'amount': amount,
            'type': transaction_type,
            'balance_after': new_balance
        })
        
        return True
    
    def simulate_trade(self, symbol: str, side: str, quantity: float, 
                      price: float, fee_rate: float = 0.001) -> bool:
        """模拟交易"""
        # 解析交易对
        if '-' in symbol:
            base_asset, quote_asset = symbol.split('-')
        elif 'USDT' in symbol:
            base_asset = symbol.replace('USDT', '')
            quote_asset = 'USDT'
        else:
            return False
        
        # 计算交易金额和手续费
        trade_amount = quantity * price
        fee = trade_amount * fee_rate
        
        if side.lower() == 'buy':
            # 买入：扣除报价资产，增加基础资产
            total_cost = trade_amount + fee
            if not self.update_balance(quote_asset, -total_cost):
                return False
            self.update_balance(base_asset, quantity)
            
        elif side.lower() == 'sell':
            # 卖出：扣除基础资产，增加报价资产
            if not self.update_balance(base_asset, -quantity):
                return False
            net_proceeds = trade_amount - fee
            self.update_balance(quote_asset, net_proceeds)
        
        else:
            return False
        
        return True
    
    def get_position(self, symbol: str) -> Dict[str, Any]:
        """获取持仓信息（期货用）"""
        return self.positions.get(symbol, {
            'symbol': symbol,
            'size': 0,
            'side': 'none',
            'entry_price': 0,
            'mark_price': 0,
            'unrealized_pnl': 0,
            'margin': 0
        })
    
    def update_position(self, symbol: str, size: float, price: float, 
                       side: str = 'long') -> bool:
        """更新持仓（期货用）"""
        if symbol not in self.positions:
            self.positions[symbol] = {
                'symbol': symbol,
                'size': 0,
                'side': 'none',
                'entry_price': 0,
                'mark_price': price,
                'unrealized_pnl': 0,
                'margin': 0
            }
        
        position = self.positions[symbol]
        
        # 更新持仓
        if position['size'] == 0:
            # 新开仓
            position['size'] = size
            position['side'] = side
            position['entry_price'] = price
        else:
            # 加仓或减仓
            if position['side'] == side:
                # 加仓
                total_value = position['size'] * position['entry_price'] + size * price
                position['size'] += size
                position['entry_price'] = total_value / position['size']
            else:
                # 减仓或反向开仓
                if size >= position['size']:
                    # 平仓并反向开仓
                    remaining_size = size - position['size']
                    position['size'] = remaining_size
                    position['side'] = side if remaining_size > 0 else 'none'
                    position['entry_price'] = price if remaining_size > 0 else 0
                else:
                    # 部分平仓
                    position['size'] -= size
        
        position['mark_price'] = price
        
        # 计算未实现盈亏
        if position['size'] > 0:
            if position['side'] == 'long':
                position['unrealized_pnl'] = position['size'] * (price - position['entry_price'])
            else:
                position['unrealized_pnl'] = position['size'] * (position['entry_price'] - price)
        else:
            position['unrealized_pnl'] = 0
        
        return True
    
    def get_account_value(self, prices: Dict[str, float]) -> float:
        """计算账户总价值"""
        total_value = 0
        
        # 现货资产价值
        for asset, balance in self.balances.items():
            if asset == 'USDT':
                total_value += balance
            else:
                price = prices.get(f"{asset}-USDT", 0)
                total_value += balance * price
        
        # 期货未实现盈亏
        for position in self.positions.values():
            total_value += position.get('unrealized_pnl', 0)
        
        return total_value
    
    def get_transaction_history(self, limit: int = 100) -> List[Dict]:
        """获取交易历史"""
        return self.transaction_history[-limit:] if limit else self.transaction_history